import { Graph, Node, Edge, Shape, ObjectExt } from '@antv/x6'
class TreeNode extends Node {
  private collapsed = false
  protected postprocess() {
    this.toggleCollapse(false)
  }
  isCollapsed() {
    return this.collapsed
  }

  toggleButtonVisibility(visible: boolean) {
    this.attr('buttonGroup', {
      display: visible ? 'block' : 'none'
    })
  }

  toggleCollapse(collapsed?: boolean) {
    const target = collapsed == null ? !this.collapsed : collapsed
    if (!target) {
      this.attr('buttonSign', {
        d: 'M 1 5 9 5 M 5 1 5 9',
        strokeWidth: 1.6
      })
    } else {
      this.attr('buttonSign', {
        d: 'M 2 5 8 5',
        strokeWidth: 1.8
      })
    }
    this.collapsed = target
  }
}

TreeNode.config({
  zIndex: 2,
  markup: [
    {
      tagName: 'rect',
      selector: 'body'
    },
    {
      tagName: 'rect',
      selector: 'name-rect'
    },
    {
      tagName: 'rect',
      selector: 'attrs-rect'
    },
    {
      tagName: 'text',
      selector: 'name-text'
    },
    {
      tagName: 'text',
      selector: 'attrs-text'
    }
  ],
  attrs: {
    rect: {
      width: 160
    },
    body: {
      stroke: '#fff',
      event: 'node:contextmenu'
    },
    'name-rect': {
      fill: '#5f95ff',
      stroke: '#fff',
      strokeWidth: 0.5
    },
    'attrs-rect': {
      fill: '#eff4ff',
      stroke: '#fff',
      strokeWidth: 0.5
    },

    'name-text': {
      ref: 'name-rect',
      refY: 0.5,
      refX: 0.5,
      textAnchor: 'middle',
      fontWeight: 'bold',
      fill: '#fff',
      fontSize: 12
    },
    'attrs-text': {
      ref: 'attrs-rect',
      refY: 0.5,
      refX: 5,
      textAnchor: 'left',
      fill: 'black',
      fontSize: 10
    }
  },
  propHooks(meta) {
    const { name, attributes, ...others } = meta

    if (!(name && attributes)) {
      return meta
    }

    const rects = [
      { type: 'name', text: name },
      { type: 'attrs', text: attributes }
    ]

    let offsetY = 0
    rects.forEach((rect) => {
      const height = rect.text.length * 12 + 16
      ObjectExt.setByPath(
        others,
        `attrs/${rect.type}-text/text`,
        rect.text.join('\n')
      )
      ObjectExt.setByPath(others, `attrs/${rect.type}-rect/height`, height)
      ObjectExt.setByPath(
        others,
        `attrs/${rect.type}-rect/transform`,
        'translate(0,' + offsetY + ')'
      )
      offsetY += height
    })

    others.size = { width: 160, height: offsetY }

    return others
  }
})

class TreeEdge extends Shape.Edge {
  isHidden() {
    const node = this.getTargetNode() as TreeNode
    return !node || !node.isVisible()
  }
}

TreeEdge.config({
  zIndex: 1,
  attrs: {
    line: {
      stroke: '#A2B1C3',
      strokeWidth: 1,
      targetMarker: null
    }
  }
})

// 注册
Node.registry.register('tree-node', TreeNode, true)
Edge.registry.register('tree-edge', TreeEdge, true)
